package com.ums.upos.service;

import android.os.RemoteException;
import android.text.TextUtils;
import com.nexgo.common.ByteUtils;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.card.cpu.APDUEntity;
import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
import com.ums.upos.GlobalDataHolder;
import com.ums.upos.uapi.ServiceResult;
import com.ums.upos.uapi.card.cpu.APDUCmd;
import com.ums.upos.uapi.card.cpu.CPUCardHandler;
import com.ums.upos.uapi.device.reader.icc.IccCardReader;
import com.ums.upos.uapi.device.reader.icc.IccReaderSlot;
import com.ums.upos.util.CardUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Created by liyang on 15-4-24.
 */
public class CPUCardHandlerBinder extends CPUCardHandler.Stub {
    private final String TAG = "CPUCardHandler";
    private Logger log;
    private IccReaderHolder iccReaderHolder = null;
    private com.nexgo.oaf.apiv3.card.cpu.CPUCardHandler sdkCPUCardHandler;

    CPUCardHandlerBinder(IccCardReader reader) {
        log = LoggerFactory.getLogger(TAG);
        for (IccReaderHolder holder : GlobalDataHolder.getInstance().getIccReaderHolderList()) {
            if (holder.getReader() == reader) {
                iccReaderHolder = holder;
                break;
            }
        }
        CardSlotTypeEnum cardSlotTypeEnum = CardSlotTypeEnum.ICC1;
        if (iccReaderHolder != null) {
            cardSlotTypeEnum = CardUtils.slotConvert(iccReaderHolder.getSlotNo());
        }
        sdkCPUCardHandler = GlobalDataHolder.getInstance().getDeviceEngine().getCPUCardHandler(cardSlotTypeEnum);
    }

    @Override
    public boolean setPowerOn(byte[] atr) throws RemoteException {
        log.info("call setPowerOn");
        try {
            if (atr == null) return false;
            boolean result;

            if (iccReaderHolder == null) return false;
            if (iccReaderHolder.getSlotNo() == IccReaderSlot.RFSlOT) {
                log.info("call setPowerOn  RFSlOT");
                if(atr != null) {
                    String uid = sdkCPUCardHandler.readUid();
                    log.info("call setPowerOn  RFSlOT uid={}",uid);
                    if (!TextUtils.isEmpty(uid)) {
                        byte[] mAtr = ByteUtils.hexString2ByteArray(uid);
                        System.arraycopy(mAtr, 0, atr, 0, (mAtr.length < atr.length ? mAtr.length : atr.length));
                    }
                }
                return true;
            }


            byte[] mAtr = new byte[64];
            result = sdkCPUCardHandler.powerOn(mAtr);
            log.debug("poweron {}", result);
            if (result) {
                log.debug("atr:{}", ByteUtils.byteArray2HexStringWithSpace(mAtr));
                //xiaox 要求转成asc码
                byte[] tmp = new byte[mAtr[0]];
                System.arraycopy(mAtr, 1, tmp, 0, mAtr[0]);
                String str = ByteUtils.byteArray2HexString(tmp);
                byte[] toAsc = ByteUtils.string2ASCIIByteArray(str);
                System.arraycopy(toAsc, 0, atr, 0, toAsc.length);
                return true;
            }
            log.debug("poweron fail");
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void setPowerOff() throws RemoteException {
        log.info("call setPowerOff");
        try {
            if (iccReaderHolder == null) return;
            sdkCPUCardHandler.powerOff();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public int exchangeAPDUCmd(APDUCmd cmd) throws RemoteException {
        log.info("call exchangeAPDUCmd");
        if (iccReaderHolder == null) return ServiceResult.Fail;
        int result;
        try {
            log.debug("APDU数据\ngetCla:" + ByteUtils.byteArray2HexStringWithSpace(new byte[]{cmd.getCla()})
                    + "\ngetIns:" + ByteUtils.byteArray2HexStringWithSpace(new byte[]{cmd.getIns()})
                    + "\ngetLc:" + cmd.getLc()
                    + "\ngetLe:" + cmd.getLe()
                    + "\ngetDataInLen:" + cmd.getDataIn().length
                    + "\ngetP1:" + ByteUtils.byteArray2HexStringWithSpace(new byte[]{cmd.getP1()})
                    + "\ngetP2:" + ByteUtils.byteArray2HexStringWithSpace(new byte[]{cmd.getP2()})
                    + "\ngetDataIn:" + ByteUtils.byteArray2HexStringWithSpace(cmd.getDataIn()));
            APDUEntity apduEntity = new APDUEntity();
            apduEntity.setCla(cmd.getCla());
            apduEntity.setIns(cmd.getIns());
            apduEntity.setP1(cmd.getP1());
            apduEntity.setP2(cmd.getP2());
            apduEntity.setLc(cmd.getLc() & 0xff);
            apduEntity.setLe(cmd.getLe() & 0xff);
            apduEntity.setDataIn(cmd.getDataIn());
            result = sdkCPUCardHandler.exchangeAPDUCmd(apduEntity);
            if (result == SdkResult.Success) {
                cmd.setSwa(apduEntity.getSwa());
                cmd.setSwb(apduEntity.getSwb());
//                cmd.setDataOut(apduEntity.getDataOut());
                byte[] data = new byte[256];
                System.arraycopy(apduEntity.getDataOut(), 0, data, 0, apduEntity.getDataOutLen());
                cmd.setDataOut(data);
                cmd.setDataOutLen(apduEntity.getDataOutLen());
                log.debug("APDU返回{},{},{},{}", ByteUtils.byteArray2HexString(cmd.getDataOut()),
                        cmd.getDataOutLen(),
                        ByteUtils.byteArray2HexString(new byte[]{cmd.getSwa()}),
                        ByteUtils.byteArray2HexString(new byte[]{cmd.getSwb()}));
                return ServiceResult.Success;
            } else {
                log.debug("exchangeAPDUCmd fail,result:{}",result);
                return ServiceResult.Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    @Override
    public boolean halt() throws RemoteException {
        log.info("call halt");
        if (iccReaderHolder == null) return false;
        if (iccReaderHolder.getSlotNo() != IccReaderSlot.RFSlOT) {
            return false;
        }
        if (iccReaderHolder.getCardType() == null) return false;
        return true;
    }

    @Override
    public boolean active() throws RemoteException {
        log.info("call active");
        if (iccReaderHolder == null) return false;
        if (iccReaderHolder.getSlotNo() != IccReaderSlot.RFSlOT) {
            return true;
        }
        //mhl20171019 判断激活状态，重复激活会导致全民付NFC交易失败
        if(GlobalDataHolder.getInstance().isRFActive())
            return true;
        return sdkCPUCardHandler.active();
    }
}
